#include "CRGeolocationManager.h"
#include "StringConverter.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "json/json.h"
#include "NGLog.h"
#include "Character.h"
#include "CharManager.h"
#include "Items.h"
#include "ItemManager.h"
#include "Users.h"
#include "UserManager.h"
#include "Channels.h"
#include "ChannelManager.h"
#include "ItemModelManager.h"
#include "Message.h"
#include "Tools.h"
#include "XMLData.h"
#include "GameDefine.h"
#include XMLDATA_MGR_PATH
#include LOGIC_MGR_PATH
#include LOG_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include "OpcodesEx.h"
#include "WorldPacket.h"
#include "AIInterface.h"
#include "url.h"


//=============================好友记录信息相关===================================
bool CRGeoLocationManager::AddCRGeoLocation(CRGeoLocation & crg)
{
	Fields fields;
	sDataMgr.initData(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, &fields);
	
	fields["type"] = crg.type;
	fields["status"] = crg.status;
	fields["uid"] = crg.uid;
	fields["gz_id"] = crg.gz_id;
	fields["agentid"] = crg.agentid;
	fields["nickname"] = crg.nickname;
	fields["icon_url"] = crg.icon_url;
	fields["gender"] = crg.gender;
	
	fields["ip"] = crg.ip;
	fields["ip_addr"] = crg.ip_addr;
	fields["addr_country"] = crg.addr_country;
	fields["addr_province"] = crg.addr_province;
	fields["addr_city"] = crg.addr_city;
	fields["addr_district"] = crg.addr_district;
	fields["addr_street"] = crg.addr_street;
	fields["addr_poiname"] = crg.addr_poiname;
	fields["addr_postal_code"] = crg.addr_postal_code;
	fields["addr_city_code"] = crg.addr_city_code;
	
	fields["coord_latitude"] = crg.coord_latitude;
	fields["coord_longitude"] = crg.coord_longitude;
	fields["coord_altitude"] = crg.coord_altitude;
	fields["coord_accuracy"] = crg.coord_accuracy;
	fields["coord_accuracy_altitude"] = crg.coord_accuracy_altitude;
	fields["coord_heading"] = crg.coord_heading;
	fields["coord_speed"] = crg.coord_speed;
	fields["coord_type"] = crg.coord_type;
	fields["coord_time"] = crg.coord_time;
	fields["geohash"] = crg.geohash;
	
	fields["client_agent_id"] = crg.client_agent_id;
	fields["client_agent_info"] = crg.client_agent_info;
	fields["create_time"] = crg.create_time;
	fields["last_time"] = crg.last_time;
	
	if (!sDataMgr.insertData(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, &fields))
		return false;
	
	crg.geo_id = fields["geo_id"].GetUInt64();
	return true;
}


bool CRGeoLocationManager::UpdateCRGeoLocation(const CRGeoLocation & crg)
{
	Fields fields;
	fields["type"] = crg.type;
	fields["status"] = crg.status;
	fields["uid"] = crg.uid;
	fields["gz_id"] = crg.gz_id;
	fields["agentid"] = crg.agentid;
	fields["nickname"] = crg.nickname;
	fields["icon_url"] = crg.icon_url;
	fields["gender"] = crg.gender;
	
	fields["ip"] = crg.ip;
	fields["ip_addr"] = crg.ip_addr;
	fields["addr_country"] = crg.addr_country;
	fields["addr_province"] = crg.addr_province;
	fields["addr_city"] = crg.addr_city;
	fields["addr_district"] = crg.addr_district;
	fields["addr_street"] = crg.addr_street;
	fields["addr_poiname"] = crg.addr_poiname;
	fields["addr_postal_code"] = crg.addr_postal_code;
	fields["addr_city_code"] = crg.addr_city_code;
	
	fields["coord_latitude"] = crg.coord_latitude;
	fields["coord_longitude"] = crg.coord_longitude;
	fields["coord_altitude"] = crg.coord_altitude;
	fields["coord_accuracy"] = crg.coord_accuracy;
	fields["coord_accuracy_altitude"] = crg.coord_accuracy_altitude;
	fields["coord_heading"] = crg.coord_heading;
	fields["coord_speed"] = crg.coord_speed;
	fields["coord_type"] = crg.coord_type;
	fields["coord_time"] = crg.coord_time;
	fields["geohash"] = crg.geohash;
	
	fields["client_agent_id"] = crg.client_agent_id;
	fields["client_agent_info"] = crg.client_agent_info;
	fields["create_time"] = crg.create_time;
	fields["last_time"] = crg.last_time;
	
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, &fields, "`geo_id` = %u", crg.geo_id);
	return count > 0;
}

#define SQLBUFER_LEN 16384

bool CRGeoLocationManager::UpdateCRGeoLocation(Fields * fields, const char * QueryString, ...)
{
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, QueryString); 
	vsnprintf(sql, SQLBUFER_LEN, QueryString, vlist); 
	va_end(vlist);
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, fields, sql);
	return count > 0;
}

bool CRGeoLocationManager::UpdateCRGeoLocation(const uint32 & crg_id, Fields * fields)
{
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, fields, "`geo_id` = %u", crg_id);
	return count > 0;
}


bool CRGeoLocationManager::GetCRGeoLocation(const uint32 & crg_id, CRGeoLocation * crg)
{
	assert (crg);
	FieldRows rows;
	sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, &rows, "`geo_id` = %u", crg_id);
	if (rows.empty())
		return false;
	
	Fields fields = rows.front();
	
	crg->geo_id = fields["geo_id"].GetUInt64();
	crg->type = fields["type"].GetUInt32();
	crg->status = fields["status"].GetUInt32();
	crg->uid = fields["uid"].GetUInt32();
	crg->gz_id = fields["gz_id"].GetUInt32();
	crg->agentid = fields["agentid"].GetUInt32();
	crg->gameid = fields["gameid"].GetUInt32();
	crg->nickname = fields["nickname"].GetValue();
	crg->icon_url = fields["icon_url"].GetValue();
	
	crg->gender = fields["gender"].GetUInt32();
	crg->ip = fields["ip"].GetValue();
	crg->ip_addr = fields["ip_addr"].GetValue();
	crg->addr_country = fields["addr_country"].GetValue();
	crg->addr_province = fields["addr_province"].GetValue();
	crg->addr_city = fields["addr_city"].GetValue();
	crg->addr_district = fields["addr_district"].GetValue();
	crg->addr_street = fields["addr_street"].GetValue();
	crg->addr_poiname = fields["addr_poiname"].GetValue();
	crg->addr_postal_code = fields["addr_postal_code"].GetValue();
	crg->addr_city_code = fields["addr_city_code"].GetValue();
	
	crg->coord_latitude = fields["coord_latitude"].GetDouble();
	crg->coord_longitude = fields["coord_longitude"].GetDouble();
	crg->coord_altitude = fields["coord_altitude"].GetDouble();
	crg->coord_accuracy = fields["coord_accuracy"].GetFloat();
	crg->coord_accuracy_altitude = fields["coord_accuracy_altitude"].GetFloat();
	crg->coord_heading = fields["coord_heading"].GetFloat();
	crg->coord_speed = fields["coord_speed"].GetFloat();
	crg->coord_type = fields["coord_type"].GetValue();
	crg->coord_time = fields["coord_time"].GetDouble();
	
	crg->geohash = fields["geohash"].GetValue();
	crg->client_agent_id = fields["client_agent_id"].GetUInt32();
	crg->client_agent_info = fields["client_agent_info"].GetValue();
	crg->create_time = fields["create_time"].GetValue();
	crg->last_time = fields["last_time"].GetUInt32();
	
	return true;
}

uint32 CRGeoLocationManager::GetCRGeoLocationList(std::list<CRGeoLocation> * lstData, const char * query,...)
{
	va_list argp;
	va_start(argp, query);
	lstData->clear();
	FieldRows fieldRows;
	
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, query); 
	vsnprintf(sql, SQLBUFER_LEN, query, vlist); 
	va_end(vlist);
	
	if (!sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CRGEOLOCATION, &fieldRows, sql))
		return 0;
	
	FieldRows::iterator iter, enditer = fieldRows.end();
	for (iter = fieldRows.begin(); iter != enditer; ++ iter)
	{
		CRGeoLocation crg;
		Fields &fields = *iter;
		
		crg.geo_id = fields["geo_id"].GetUInt64();
		crg.type = fields["type"].GetUInt32();
		crg.status = fields["status"].GetUInt32();
		crg.uid = fields["uid"].GetUInt32();
		crg.gz_id = fields["gz_id"].GetUInt32();
		crg.agentid = fields["agentid"].GetUInt32();
		crg.gameid = fields["gameid"].GetUInt32();
		crg.nickname = fields["nickname"].GetValue();
		crg.icon_url = fields["icon_url"].GetValue();
		
		crg.gender = fields["gender"].GetUInt32();
		crg.ip = fields["ip"].GetValue();
		crg.ip_addr = fields["ip_addr"].GetValue();
		crg.addr_country = fields["addr_country"].GetValue();
		crg.addr_province = fields["addr_province"].GetValue();
		crg.addr_city = fields["addr_city"].GetValue();
		crg.addr_district = fields["addr_district"].GetValue();
		crg.addr_street = fields["addr_street"].GetValue();
		crg.addr_poiname = fields["addr_poiname"].GetValue();
		crg.addr_postal_code = fields["addr_postal_code"].GetValue();
		crg.addr_city_code = fields["addr_city_code"].GetValue();
		
		crg.coord_latitude = fields["coord_latitude"].GetDouble();
		crg.coord_longitude = fields["coord_longitude"].GetDouble();
		crg.coord_altitude = fields["coord_altitude"].GetDouble();
		crg.coord_accuracy = fields["coord_accuracy"].GetFloat();
		crg.coord_accuracy_altitude = fields["coord_accuracy_altitude"].GetFloat();
		crg.coord_heading = fields["coord_heading"].GetFloat();
		crg.coord_speed = fields["coord_speed"].GetFloat();
		crg.coord_type = fields["coord_type"].GetValue();
		crg.coord_time = fields["coord_time"].GetDouble();
		
		crg.geohash = fields["geohash"].GetValue();
		crg.client_agent_id = fields["client_agent_id"].GetUInt32();
		crg.client_agent_info = fields["client_agent_info"].GetValue();
		crg.create_time = fields["create_time"].GetValue();
		crg.last_time = fields["last_time"].GetUInt32();
		
		lstData->push_back(crg);
	}
	
	return lstData->size();
}


// 获得玩家经纬度 longitude 精度 latitude 纬度 altitude 海拔
bool CRGeoLocationManager::GetUserLongitudeAndLatitude(const uint32 & pid, double & longitude, double & latitude, double & altitude)
{
	if(pid == 0)
		return false;
	
	std::list<CRGeoLocation> lstData;
	if(!GetCRGeoLocationList(&lstData, "uid = %u", pid))
		return false;
	
	CRGeoLocation crGL = lstData.front();
	
	longitude = crGL.coord_longitude;	// 精度
	latitude = crGL.coord_latitude;		// 纬度
	altitude = crGL.coord_altitude;		// 海拔
	return true;
}
